﻿using Microsoft.EntityFrameworkCore;
using Order.Api.Read.Application.Command;
using Order.Api.Read.Dto.Order;
using Order.Api.Read.Service.RefundService;
using Order.ErrorCode;
using Order.Domain.OrderDomain;
using Order.Interstructrue;
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Reflection;

namespace Order.Api.Read.Service.RefundService
{
    /// <summary>
    /// 退款服务实现类
    /// 提供退款相关的业务逻辑处理
    /// </summary>
    public class RefundService : IRefundService
    {
        private readonly MedicalDbContext _context;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="context">数据库上下文</param>
        public RefundService(MedicalDbContext context)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context), "数据库上下文不能为空");
        }

        /// <summary>
        /// 获取退款分页数据
        /// 支持关键字搜索、时间范围筛选
        /// </summary>
        /// <param name="command">分页查询命令</param>
        /// <returns>分页结果</returns>
        /// <exception cref="ArgumentNullException">当command为null时抛出</exception>
        public async Task<ApiPageIng<Refund>> GetRefundPageAsync(RefundPageCommand command)
        {
            try
            {
                // 参数验证
                if (command == null)
                {
                    throw new ArgumentNullException(nameof(command), "查询命令不能为空");
                }

                // 验证查询条件
                if (command.Query == null)
                {
                    command.Query = new RefundQueryDto();
                }

                // 验证分页参数
                if (command.Query.PageIndex <= 0)
                {
                    command.Query.PageIndex = 1;
                }

                if (command.Query.PageSize <= 0)
                {
                    command.Query.PageSize = 10;
                }

                // 构建基础查询
                var query = _context.Refund.AsQueryable();

                // 应用关键字查询条件
                if (!string.IsNullOrEmpty(command.Query.Keyword))
                {
                    var keyword = command.Query.Keyword.Trim();

                    query = query.Where(x =>
                        // 基础字段查询：退款单号、处理人、备注
                        (x.RefundNo != null && x.RefundNo.Contains(keyword)) ||
                        (x.ProcessedName != null && x.ProcessedName.Contains(keyword)) ||
                        (x.Remark != null && x.Remark.Contains(keyword)) ||

                        // 通过订单信息查询患者信息（确保OrderId和PatientId不为空）
                        (x.OrderType.HasValue && x.OrderId.HasValue &&
                        (
                            // 问诊订单查询：通过患者姓名和手机号
                            (x.OrderType == Order.Domain.Enum.OrderTypeEnum.问诊订单 &&
                             _context.InterrogationOrder.Any(io => io.Id == x.OrderId &&
                                 io.PatientId.HasValue &&
                                 _context.Patient.Any(p => p.Id == io.PatientId &&
                                     (p.PatientName != null && p.PatientName.Contains(keyword) ||
                                      p.Phone != null && p.Phone.Contains(keyword))))) ||

                            // 处方订单查询：通过患者姓名和手机号
                            (x.OrderType == Order.Domain.Enum.OrderTypeEnum.处方订单 &&
                             _context.PrescriptionOrder.Any(po => po.Id == x.OrderId &&
                                 po.PatientId.HasValue &&
                                 _context.Patient.Any(p => p.Id == po.PatientId &&
                                     (p.PatientName != null && p.PatientName.Contains(keyword) ||
                                      p.Phone != null && p.Phone.Contains(keyword))))) ||

                            // 挂号订单查询：通过患者姓名和手机号
                            (x.OrderType == Order.Domain.Enum.OrderTypeEnum.挂号订单 &&
                             _context.RegistrationOrder.Any(ro => ro.Id == x.OrderId &&
                                 ro.PatientId.HasValue &&
                                 _context.Patient.Any(p => p.Id == ro.PatientId &&
                                     (p.PatientName != null && p.PatientName.Contains(keyword) ||
                                      p.Phone != null && p.Phone.Contains(keyword))))) ||

                            // 药品订单查询：通过订单编号和患者信息
                            (x.OrderType == Order.Domain.Enum.OrderTypeEnum.药品订单 &&
                             _context.DrugOrders.Any(drugOrder => drugOrder.Id == x.OrderId &&
                                 (drugOrder.OrderNo != null && drugOrder.OrderNo.Contains(keyword) ||
                                  drugOrder.PatientId.HasValue &&
                                  _context.Patient.Any(p => p.Id == drugOrder.PatientId &&
                                      (p.PatientName != null && p.PatientName.Contains(keyword) ||
                                       p.Phone != null && p.Phone.Contains(keyword))))))
                        ))
                    );
                }

                // 应用时间范围筛选
                if (command.Query.StartTime.HasValue)
                {
                    query = query.Where(x => x.CreateTime >= command.Query.StartTime.Value);
                }

                if (command.Query.EndTime.HasValue)
                {
                    query = query.Where(x => x.CreateTime <= command.Query.EndTime.Value);
                }

                // 应用退款状态筛选
                if (command.Query.RefundStatus.HasValue)
                {
                    query = query.Where(x => x.RefundStatus == command.Query.RefundStatus.Value);
                }

                // 获取总数
                var totalCount = await query.CountAsync();

                // 分页查询
                var pageData = await query
                    .OrderByDescending(x => x.CreateTime) // 按创建时间倒序排列
                    .Skip((command.Query.PageIndex - 1) * command.Query.PageSize)
                    .Take(command.Query.PageSize)
                    .ToListAsync();

                // 返回分页结果
                return new ApiPageIng<Refund>
                {
                    Data = pageData,
                    TotalCount = totalCount,
                    PageIndex = command.Query.PageIndex,
                    PageSize = command.Query.PageSize
                };
            }
            catch (Exception ex)
            {
                // 记录异常日志
                // TODO: 添加日志记录
                throw new Exception($"获取退款分页数据时发生错误: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取退款详情
        /// 根据退款ID查询详细信息，包括关联的订单和患者信息
        /// </summary>
        /// <param name="id">退款ID</param>
        /// <returns>退款详情DTO，如果未找到则返回null</returns>
        /// <exception cref="ArgumentException">当id小于等于0时抛出</exception>
        public async Task<RefundDetailDto> GetRefundDetailAsync(int id)
        {
            try
            {
                // 参数验证
                if (id <= 0)
                {
                    throw new ArgumentException("退款ID必须大于0", nameof(id));
                }

                // 查询退款基本信息
                var refund = await _context.Refund.FirstOrDefaultAsync(x => x.Id == id);
                if (refund == null)
                {
                    // 退款记录不存在，返回null
                    return null;
                }

                // 构建退款详情DTO
                var refundDetail = new RefundDetailDto
                {
                    Id = refund.Id,
                    RefundNo = refund.RefundNo,
                    RefundStatus = refund.RefundStatus,
                    CreateTime = refund.CreateTime,
                    RefundAmount = refund.RefundAmount,
                    RefundMethod = refund.RefundMethod,
                    OrderType = refund.OrderType,
                    RefundSource = refund.RefundSource,
                    ProcessedTime = refund.ProcessedTime,
                    ProcessedName = refund.ProcessedName,
                    Remark = refund.Remark
                };

                // 设置枚举描述
                refundDetail.RefundStatusDesc = GetEnumDescription(refund.RefundStatus);
                refundDetail.RefundMethodDesc = GetEnumDescription(refund.RefundMethod);
                refundDetail.OrderTypeDesc = GetEnumDescription(refund.OrderType);
                refundDetail.RefundSourceDesc = GetEnumDescription(refund.RefundSource);

                // 根据订单类型查询对应的订单信息和患者信息
                if (refund.OrderType.HasValue && refund.OrderId.HasValue)
                {
                    try
                    {
                        switch (refund.OrderType.Value)
                        {
                            case Order.Domain.Enum.OrderTypeEnum.问诊订单:
                                await LoadInterrogationOrderInfo(refund.OrderId.Value, refundDetail);
                                break;

                            case Order.Domain.Enum.OrderTypeEnum.处方订单:
                                await LoadPrescriptionOrderInfo(refund.OrderId.Value, refundDetail);
                                break;

                            case Order.Domain.Enum.OrderTypeEnum.挂号订单:
                                await LoadRegistrationOrderInfo(refund.OrderId.Value, refundDetail);
                                break;

                            case Order.Domain.Enum.OrderTypeEnum.药品订单:
                                await LoadDrugOrderInfo(refund.OrderId.Value, refundDetail);
                                break;

                            default:
                                // 未知的订单类型，记录警告但不抛出异常
                                // TODO: 添加日志记录
                                break;
                        }
                    }
                    catch (Exception ex)
                    {
                        // 查询关联订单信息时发生错误，记录但不影响主流程
                        // TODO: 添加日志记录
                        // 可以选择是否重新抛出异常，这里选择继续执行
                    }
                }

                return refundDetail;
            }
            catch (Exception ex)
            {
                // 记录异常日志
                // TODO: 添加日志记录
                throw new Exception($"获取退款详情时发生错误: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取枚举描述
        /// </summary>
        /// <typeparam name="T">枚举类型</typeparam>
        /// <param name="enumValue">枚举值</param>
        /// <returns>枚举描述，如果没有Description特性则返回枚举名称</returns>
        private string? GetEnumDescription<T>(T? enumValue) where T : struct, Enum
        {
            try
            {
                if (!enumValue.HasValue)
                    return null;

                var enumType = enumValue.Value.GetType();
                var field = enumType.GetField(enumValue.Value.ToString());

                if (field == null)
                    return enumValue.Value.ToString();

                var attributes = field.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false);

                if (attributes.Length > 0 && attributes[0] is System.ComponentModel.DescriptionAttribute descriptionAttribute)
                {
                    return descriptionAttribute.Description;
                }

                // 如果没有Description特性，返回枚举名称
                return enumValue.Value.ToString();
            }
            catch (Exception ex)
            {
                // 记录异常日志
                // TODO: 添加日志记录
                // 返回枚举名称作为后备方案
                return enumValue?.ToString();
            }
        }

        /// <summary>
        /// 加载问诊订单信息
        /// </summary>
        /// <param name="orderId">订单ID</param>
        /// <param name="refundDetail">退款详情DTO</param>
        private async Task LoadInterrogationOrderInfo(int orderId, RefundDetailDto refundDetail)
        {
            var interrogationOrder = await _context.InterrogationOrder
                .FirstOrDefaultAsync(io => io.Id == orderId);

            if (interrogationOrder != null)
            {
                refundDetail.OrderNo = interrogationOrder.OrderNo;

                // 查询患者信息
                if (interrogationOrder.PatientId.HasValue)
                {
                    var patient = await _context.Patient
                        .FirstOrDefaultAsync(p => p.Id == interrogationOrder.PatientId.Value);
                    refundDetail.UserPhone = patient?.Phone;
                }
            }
        }

        /// <summary>
        /// 加载处方订单信息
        /// </summary>
        /// <param name="orderId">订单ID</param>
        /// <param name="refundDetail">退款详情DTO</param>
        private async Task LoadPrescriptionOrderInfo(int orderId, RefundDetailDto refundDetail)
        {
            var prescriptionOrder = await _context.PrescriptionOrder
                .FirstOrDefaultAsync(po => po.Id == orderId);

            if (prescriptionOrder != null)
            {
                refundDetail.OrderNo = prescriptionOrder.OrderNo;
                refundDetail.OrderAmount = prescriptionOrder.Cost;

                // 查询患者信息
                if (prescriptionOrder.PatientId.HasValue)
                {
                    var patient = await _context.Patient
                        .FirstOrDefaultAsync(p => p.Id == prescriptionOrder.PatientId.Value);
                    refundDetail.UserPhone = patient?.Phone;
                }
            }
        }

        /// <summary>
        /// 加载挂号订单信息
        /// </summary>
        /// <param name="orderId">订单ID</param>
        /// <param name="refundDetail">退款详情DTO</param>
        private async Task LoadRegistrationOrderInfo(int orderId, RefundDetailDto refundDetail)
        {
            var registrationOrder = await _context.RegistrationOrder
                .FirstOrDefaultAsync(ro => ro.Id == orderId);

            if (registrationOrder != null)
            {
                refundDetail.OrderNo = registrationOrder.OrderNo;
                refundDetail.OrderAmount = registrationOrder.Amount;

                // 查询患者信息
                if (registrationOrder.PatientId.HasValue)
                {
                    var patient = await _context.Patient
                        .FirstOrDefaultAsync(p => p.Id == registrationOrder.PatientId.Value);
                    refundDetail.UserPhone = patient?.Phone;
                }
            }
        }

        /// <summary>
        /// 加载药品订单信息
        /// </summary>
        /// <param name="orderId">订单ID</param>
        /// <param name="refundDetail">退款详情DTO</param>
        private async Task LoadDrugOrderInfo(int orderId, RefundDetailDto refundDetail)
        {
            var drugOrder = await _context.DrugOrders
                .FirstOrDefaultAsync(drugOrder => drugOrder.Id == orderId);

            if (drugOrder != null)
            {
                refundDetail.OrderNo = drugOrder.OrderNo;
                refundDetail.OrderAmount = drugOrder.OrderAmount;

                // 查询患者信息
                if (drugOrder.PatientId.HasValue)
                {
                    var patient = await _context.Patient
                        .FirstOrDefaultAsync(p => p.Id == drugOrder.PatientId.Value);
                    refundDetail.UserPhone = patient?.Phone;
                }
            }
        }
    }
}
